package com.zj.web.controller;

import com.zj.config.AIConfig;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.chat.StreamingChatModel;
import dev.langchain4j.model.chat.response.ChatResponse;
import dev.langchain4j.model.chat.response.StreamingChatResponseHandler;
import dev.langchain4j.service.TokenStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

@RestController
@RequestMapping("/ai")
public class ChatController {
    /**
     * 低级别的模型  直接调用chatModel.chat(message)
     */
    @Autowired
    private ChatModel chatModel;
    //低级别的模型
    //访问路径：http://localhost:8888/ai/chat/{message}
    @RequestMapping("/chat")
    public String chat(@RequestParam("message") String message) {
        return chatModel.chat(message);
    }
    /**
     * 暂时还不是流式输出，只是将值打印在后台 没有返回值（前端得不到数据）
     * 引入流式chatmodel，但是响应还不是流式的
     */
    @Autowired
    private StreamingChatModel streamingChatModel;
    //高级别的模型 流式输出  没有返回值（前端得不到数据）
    //访问路径：http://localhost:8888/ai/streamingChat/{message}
    @RequestMapping("/streamingChat")
    public void streamingChat(@RequestParam("message") String message) {
        streamingChatModel.chat(message, new StreamingChatResponseHandler() {

            @Override
            public void onPartialResponse(String s) {
                System.out.println(s);
            }

            @Override
            public void onCompleteResponse(ChatResponse chatResponse) {
                System.out.println("===========================");
                System.out.println(chatResponse.toString());
                System.out.println("===========================");
            }

            @Override
            public void onError(Throwable throwable) {
                System.out.println("***************************");
                System.out.println(throwable.getMessage());
                System.out.println("***************************");
            }
        });
    }
    /**
     * 引入流式chatmodel，流式响应，前端有数据，流式输出
     * 要返回一个flux流，前端才能得到数据
     */
    @RequestMapping(value = "/streamingChat2", produces = "text/stream;charset=utf-8")
    public Flux<String> streamingChat2(@RequestParam("message") String message) {
        //创建一个flux流，用于向订阅者发送数据，sink是通道
        Flux<String> flux = Flux.create(sink -> {
            streamingChatModel.chat(message, new StreamingChatResponseHandler() {

                @Override
                public void onPartialResponse(String s) {
                    //得到部分响应结果，要放到flux中，向订阅者发送
                    sink.next(s);
                }

                @Override
                public void onCompleteResponse(ChatResponse chatResponse) {
                    //响应完成，关闭flux
                    sink.complete();
                }

                @Override
                public void onError(Throwable throwable) {
                    //发生错误，关闭flux
                    sink.error(throwable);
                }
            });
        });
        return flux;
    }


    @Autowired
    private AIConfig.AiAssistant aiAssistant;
    //访问路径：http://localhost:15000/ai/assistantchat?memoryId=1&message=你好
    @RequestMapping("/assistantchat")
    public String assistantchat(@RequestParam("memoryId") String memoryId,
                                @RequestParam("message") String message){
        return aiAssistant.chat(memoryId,message);
    }

    //访问路径：http://localhost:15000/ai/assistantchatstream?memoryId=1&message=你好
    //produces = "text/stream;charset=utf-8"  表示返回的是流式数据,告诉浏览器传入的是流式数据
    //GET请求
    @RequestMapping(value = "/assistantchatstream", produces = "text/stream;charset=utf-8")
    public Flux<String> assistantchat2(@RequestParam("memoryId") String memoryId,
                                @RequestParam("message") String message){
        TokenStream tokenStream = aiAssistant.chatStream(memoryId, message);
        return Flux.create(sink -> {
            tokenStream.onPartialResponse(s -> sink.next(s))
                .onCompleteResponse(s -> sink.complete())
                .onError(error -> sink.error(error)).start();
        });
    }
}

//LowLevel 低级别的
//先一次性输出所有的内容-->流式输出在输出框-->流式输出在前端